Given an m x n matrix mat, return an array of all the elements of the array in a diagonal order.
Example 1:

Input: mat = [[1,2,3],[4,5,6],[7,8,9]]
Output: [1,2,4,7,5,3,6,8,9]
Example 2:
Input: mat = [[1,2],[3,4]]
Output: [1,2,3,4]
Constraints:
m == mat.length
n == mat[i].length
1 <= m, n <= 104
1 <= m * n <= 104
105 <= mat[i][j] <= 105
這題解法是由幾個if-else 判斷組成的,要判斷什麼時候往右上走或是往左下走,到後半部分轉換的時候也要注意邊界問題,所以判斷的先後順序也要調整。
首先,座標和為0或偶數時往右上走,反之則往左下走,再來自己畫33 跟44 的圖,比較一下邊界應該就知道座標怎麼加減了。
Runtime: 2 ms (98.5%)
Memory Usage: 46.2 MB (42.51%)
class Solution {
    public int[] findDiagonalOrder(int[][] mat) {
        int m = 0, n = 0;
        int[] result = new int[mat.length * mat[0].length];
        for (int i = 0, size = result.length, ml = mat.length - 1, nl = mat[0].length  -1; i < size; i++) {
            result[i] = mat[m][n];
            if ((m + n) % 2 == 0) {
                if (n == nl) m++;
                else if (m == 0) n++;
                else {
                    m--;
                    n++;
                }
            } else {
                if (m == ml) n++;
                else if (n == 0) m++;
                else {
                    m++;
                    n--;
                }
            }
        }
        return result;
    }
}
Given an m x n matrix, return all elements of the matrix in spiral order.
Example 1:

Input: matrix = [[1,2,3],[4,5,6],[7,8,9]]
Output: [1,2,3,6,9,8,7,4,5]
Example 2:

Input: matrix = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]
Output: [1,2,3,4,8,12,11,10,9,5,6,7]
Constraints:
m == matrix.length
n == matrix[i].length
1 <= m, n <= 10
100 <= matrix[i][j] <= 100
第一個解法是優化前的做法,使用多個變數儲存m 和n 的最大及最小值,當遇到邊界時則轉向。
Runtime: 0 ms (100%)
Memory Usage: 40.9 MB (18.93%)
class Solution {
    public List<Integer> spiralOrder(int[][] matrix) {
        List<Integer> result = new ArrayList<>();
        int mMin = 0, mMax = matrix.length - 1, nMin = 0, nMax = matrix[0].length - 1;
        int m = 0, n = 0, direct = 0;
        for (int i = 0; i < matrix.length*matrix[0].length; i++) {
            result.add(matrix[m][n]);
            switch (direct) {
                case 0:
                    if (n != nMax) {
                        n++;
                    } else {
                        m++;
                        mMin++;
                        direct = 1;
                    }
                    break;
                case 1:
                    if (m != mMax) {
                        m++;
                    } else {
                        n--;
                        nMax--;
                        direct = 2;
                    }
                    break;
                case 2:
                    if (n != nMin) {
                        n--;
                    } else {
                        m--;
                        mMax--;
                        direct = 3;
                    }
                    break;
                case 3:
                    if (m != mMin) {
                        m--;
                    } else {
                        n++;
                        nMin++;
                        direct = 0;
                    }
                    break;
            }
        }
        return result;
    }
}
由於第一個解法在記憶體表現上不佳,繼續思考解法後發現並不需要特別使用m 和n 去移動座標,只會在某一個邊界上移動,因此可以省去一些變數。
Runtime: 0 ms (100%)
Memory Usage: 40.2 MB (87.39%)
class Solution {
    public List<Integer> spiralOrder(int[][] matrix) {
        List<Integer> result = new ArrayList<>();
        int mMin = 0, mMax = matrix.length - 1, nMin = 0, nMax = matrix[0].length - 1;
        while (mMin <= mMax && nMin <= nMax) {
            // right
            if (mMin <= mMax && nMin <= nMax) {
                for (int i = nMin; i <= nMax; i++) {
                    result.add(matrix[mMin][i]);
                }
                mMin++;
            }
            // down
            if (mMin <= mMax && nMin <= nMax) {
                for (int i = mMin; i <= mMax; i++) {
                    result.add(matrix[i][nMax]);
                }
                nMax--;
            }
            // left
            if (mMin <= mMax && nMin <= nMax) {
                for (int i = nMax; i >= nMin; i--) {
                    result.add(matrix[mMax][i]);
                }
                mMax--;
            }
            // up
            if (mMin <= mMax && nMin <= nMax) {
                for (int i = mMax; i >= mMin; i--) {
                    result.add(matrix[i][nMin]);
                }
                nMin++;
            }
        }
        return result;
    }
}
這兩題都是Medium 的題目,解法上需要再多考慮各種情況,常常寫出一個解法但在某些情況下會出錯,在加了一堆判斷想要規避例外狀況後,發現應該是解法上的問題,因此解題上應該要習慣拿紙筆出來,做一些筆記跟計算才比較容易想出解法。
